package com.meiyuetao.myt.sale.web.action;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import lab.s2jh.auth.entity.Role;
import lab.s2jh.auth.entity.User;
import lab.s2jh.auth.service.RoleService;
import lab.s2jh.core.annotation.MetaData;
import lab.s2jh.core.pagination.GroupPropertyFilter;
import lab.s2jh.core.security.AuthContextHolder;
import lab.s2jh.core.service.BaseService;
import lab.s2jh.core.service.Validation;
import lab.s2jh.core.web.annotation.SecurityControlIgnore;
import lab.s2jh.core.web.view.OperationResult;
import lab.s2jh.ctx.FreemarkerService;

import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.rest.HttpHeaders;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.meiyuetao.myt.core.constant.StorageModeEnum;
import com.meiyuetao.myt.core.constant.VoucherStateEnum;
import com.meiyuetao.myt.core.constant.VoucherTypeEnum;
import com.meiyuetao.myt.core.service.SolrService;
import com.meiyuetao.myt.core.service.VoucherNumGenerateService;
import com.meiyuetao.myt.core.web.MytBaseController;
import com.meiyuetao.myt.finance.entity.AccountInOut;
import com.meiyuetao.myt.finance.entity.AccountSubject;
import com.meiyuetao.myt.finance.service.AccountInOutService;
import com.meiyuetao.myt.finance.service.AccountSubjectService;
import com.meiyuetao.myt.job.BusinessNotifyService;
import com.meiyuetao.myt.partner.entity.Partner;
import com.meiyuetao.myt.partner.service.PartnerService;
import com.meiyuetao.myt.purchase.entity.Supplier;
import com.meiyuetao.myt.sale.entity.ExpressDataTemplate;
import com.meiyuetao.myt.sale.entity.SaleDelivery;
import com.meiyuetao.myt.sale.entity.SaleDelivery.DeliveryProcessTypeEnum;
import com.meiyuetao.myt.sale.entity.SaleDeliveryDetail;
import com.meiyuetao.myt.sale.entity.SaleDeliveryPic;
import com.meiyuetao.myt.sale.service.ExpressDataTemplateService;
import com.meiyuetao.myt.sale.service.SaleDeliveryService;
import com.meiyuetao.myt.sale.vo.SaleAndReturnDetailVo;
import com.meiyuetao.myt.stock.entity.StockInOut;
import com.meiyuetao.myt.stock.entity.StorageLocation;
import com.meiyuetao.myt.stock.service.StockInOutService;
import com.meiyuetao.myt.stock.service.StorageLocationService;

@MetaData("SaleDeliveryController")
public class SaleDeliveryController extends MytBaseController<SaleDelivery, Long> {

    @Autowired
    private SaleDeliveryService saleDeliveryService;
    @Autowired
    private VoucherNumGenerateService voucherNumGenerateService;
    @Autowired
    private StorageLocationService storageLocationService;
    @Autowired
    private ExpressDataTemplateService expressDataTemplateService;
    @Autowired
    private AccountSubjectService accountSubjectService;
    @Autowired
    private StockInOutService stockInOutService;
    @Autowired
    private AccountInOutService accountInOutService;
    @Autowired
    private PartnerService partnerService;
    @Autowired
    private RoleService roleService;

    @Autowired
    private BusinessNotifyService businessNotifyService;
    @Autowired
    private FreemarkerService freemarkerService;

    @Autowired
    private SolrService solrService;

    private String geocode;

    @Override
    protected BaseService<SaleDelivery, Long> getEntityService() {
        return saleDeliveryService;
    }

    @Override
    protected void checkEntityAclPermission(SaleDelivery entity) {

    }

    @Override
    protected void setupDetachedBindingEntity(Long id) {
        bindingEntity = getEntityService().findDetachedOne(id, "saleDeliveryDetails", "saleDeliveryPics");
    }

    public HttpHeaders saleAndReturnDatas() {
        String kw = this.getParameter("kw");
        Date begin = null;
        Date end = null;

        String date = this.getParameter("date");
        String[] dates = date.split("～");
        if (StringUtils.isNotBlank(date) && dates.length >= 2) {
            begin = new DateTime(dates[0].trim()).toDate();
            end = new DateTime(dates[1].trim()).toDate();
        } else {
            begin = new DateTime("2000-1-1").toDate();
            end = new Date();
        }

        String[] voucherTypes = this.getParameterIds("voucherType");

        List<SaleAndReturnDetailVo> list = saleDeliveryService.findSaleAndReturnLists(kw, begin, end, voucherTypes);
        setModel(buildPageResultFromList(list));
        return buildDefaultHttpHeaders();
    }

    public HttpHeaders getMinimumDistancePartner() {
        String sid = solrService.findMinimumDistancePartner(geocode);
        // String sid = "24";
        if (sid != null) {
            Long sidLong = Long.parseLong(sid);
            setModel(partnerService.findOne(sidLong));
        } else {
            setModel("NULL");
        }
        return buildDefaultHttpHeaders();
    }

    @Override
    public String isDisallowUpdate() {
        if (VoucherStateEnum.REDW.equals(bindingEntity.getVoucherState())) {
            return "已红冲的不能修改";
        }

        return null;
    }

    public String isDisallowChargeAgainst() {

        if (VoucherStateEnum.REDW.equals(bindingEntity.getVoucherState())) {
            return "已红冲";
        }

        return null;
    }

    public void prepareBpmNew() {
        bindingEntity = new SaleDelivery();
        bindingEntity.setVoucher(voucherNumGenerateService.getVoucherNumByType(VoucherTypeEnum.XS));
        bindingEntity.setVoucherDate(new Date());
        bindingEntity.setVoucherUser(getLogonUser());
        bindingEntity.setVoucherDepartment(getLogonUser().getDepartment());
    }

    @MetaData("创建初始化")
    public HttpHeaders bpmNew() {
        return buildDefaultHttpHeaders("bpmInput");
    }

    @MetaData("采购订单保存")
    public HttpHeaders bpmSave() {
        Set<StorageLocation> storageLocations = Sets.newHashSet();
        for (SaleDeliveryDetail sdd : bindingEntity.getSaleDeliveryDetails()) {
            Validation.isTrue(sdd.getStorageLocation() != null, "发货仓库不能为空");
            storageLocations.add(sdd.getStorageLocation());

        }
        Validation.isTrue(storageLocations.size() == 1, "同一销售单商品库存地必须一致");
        Boolean flag = true;
        for (SaleDeliveryDetail sdd : bindingEntity.getSaleDeliveryDetails()) {
            StorageLocation storageLocation = storageLocationService.findOne(sdd.getStorageLocation().getId());
            if (!bindingEntity.getStorageMode().equals(storageLocation.getStorageMode())) {
                flag = false;
                break;
            }

        }
        Validation.isTrue(flag, "销售单库存模式和商品库存地的模式不一致");
        Map<String, Object> variables = Maps.newHashMap();
        String submitToAudit = this.getParameter("submitToAudit");
        if (BooleanUtils.toBoolean(submitToAudit)) {
            bindingEntity.setLastOperationSummary(bindingEntity.buildLastOperationSummary("提交"));
            bindingEntity.setProcessType(DeliveryProcessTypeEnum.POST);
            bindingEntity.setSubmitDate(new Date());
        }

        List<SaleDeliveryDetail> SaleDeliveryDetails = bindingEntity.getSaleDeliveryDetails();

        List<Long> commodityIds = new ArrayList<Long>();
        for (SaleDeliveryDetail saleDeliveryDetail : SaleDeliveryDetails) {
            saleDeliveryDetail.setSaleDelivery(bindingEntity);
            commodityIds.add(saleDeliveryDetail.getCommodity().getId());
        }

        Partner partner = bindingEntity.getAgentPartner();
        if (partner != null) {
            Long partnerId = partner.getId();
            partner = partnerService.findOne(partnerId);
            /*
             * 校验所选商品是否属于同一代理商父子路径
             */
            // 检测本次提交表单没有用户已confirm确认标识，则进行相关预警校验检查
            if (postNotConfirmedByUser()) {
                List<String> messages = Lists.newArrayList();
                if (!partnerService.checkCommodityAgentPartners(commodityIds, partner)) {// 不是同一分销商提示用户
                    messages.add("当前销售单所有商品不属于同一个代理系列，会导致无法合理的指派分销商");
                }
                if (messages.size() > 0) {
                    setModel(OperationResult.buildConfirmResult("销售单数据处理警告", messages));
                    // 直接返回使用户进行Confirm确认
                    return buildDefaultHttpHeaders();
                }
            }
        }
        if (StringUtils.isNotBlank(getParameter("payedAmount")) && StringUtils.isBlank(getParameter("accountSubject.id"))) {
            Validation.isTrue(false, "如有收款金额则必须选取收款账户");
        }

        if (bindingEntity.isNew()) {
            // 销售单页面如果没有输入“关联订单号”，则提交处理逻辑中兼容处理取凭证号赋值给“关联订单号”
            if (StringUtils.isBlank(bindingEntity.getReferenceVoucher())) {
                bindingEntity.setReferenceVoucher(bindingEntity.getVoucher());
            }
            saleDeliveryService.bpmCreate(bindingEntity, variables);
            setModel(OperationResult.buildSuccessResult("销售单创建完成，并同步启动处理流程", bindingEntity));
        } else {
            saleDeliveryService.bpmUpdate(bindingEntity, this.getRequiredParameter("taskId"), variables);
            setModel(OperationResult.buildSuccessResult("销售单任务提交完成", bindingEntity));
        }
        return buildDefaultHttpHeaders();
    }

    @MetaData("一线审核")
    public HttpHeaders bpmLevel1Audit() {
        Map<String, Object> variables = Maps.newHashMap();
        variables.put("auditLevel1Time", new Date());
        variables.put("auditLevel1User", AuthContextHolder.getAuthUserPin());
        Boolean auditLevel1Pass = new Boolean(getRequiredParameter("auditLevel1Pass"));
        variables.put("auditLevel1Pass", auditLevel1Pass);
        variables.put("auditLevel1Explain", getParameter("auditLevel1Explain"));
        bindingEntity.setLastOperationSummary(bindingEntity.buildLastOperationSummary("审核"));
        bindingEntity.setAuditBy(AuthContextHolder.getAuthUserPin());
        if (!auditLevel1Pass) {
            bindingEntity.setSubmitDate(null);
            bindingEntity.setProcessType(DeliveryProcessTypeEnum.REJECT);
        }
        saleDeliveryService.bpmUpdate(bindingEntity, this.getRequiredParameter("taskId"), variables);
        setModel(OperationResult.buildSuccessResult("销售单一线审核完成", bindingEntity));
        return buildDefaultHttpHeaders();
    }

    @Override
    @MetaData("保存")
    public HttpHeaders doSave() {
        List<SaleDeliveryPic> saleDeliveryPices = bindingEntity.getSaleDeliveryPics();
        if (saleDeliveryPices != null && saleDeliveryPices.size() > 0) {
            for (SaleDeliveryPic saleDeliveryPic : saleDeliveryPices) {
                saleDeliveryPic.setSaleDelivery(bindingEntity);
            }
        }

        boolean saved = false;
        // && StringUtils.isNotBlank(bindingEntity.getLogisticsNo())
        if (bindingEntity.getLogistics() != null) {
            SaleDelivery dbEntity = saleDeliveryService.findOne(bindingEntity.getId());
            Supplier logistics = dbEntity.getLogistics();
            if (logistics == null) {
                // 首次设置快递公司
                saleDeliveryService.deliverySave(bindingEntity);
                setModel(OperationResult.buildSuccessResult("发货成功", bindingEntity));
                saved = true;
            }
        }

        if (!saved) {
            saleDeliveryService.save(bindingEntity);
            setModel(OperationResult.buildSuccessResult("数据保存成功", bindingEntity));
        }
        return buildDefaultHttpHeaders();
    }

    @Override
    @MetaData("查询")
    public HttpHeaders findByPage() {
        return super.findByPage();
    }

    public void preparePickingDetails() {
        bindingEntity = saleDeliveryService.findByProperty("voucher", getRequiredParameter("voucher"));
    }

    @MetaData("发货显示")
    public HttpHeaders viewDelivery() {
        return buildDefaultHttpHeaders("delivery");
    }

    @MetaData("拣货明细")
    public HttpHeaders pickingDetails() {
        return buildDefaultHttpHeaders("picking-details");
    }

    public void prepareDeliveryDetails() {
        bindingEntity = saleDeliveryService.findByProperty("voucher", getRequiredParameter("voucher"));
    }

    @MetaData("发货明细")
    public HttpHeaders deliveryDetails() {
        return buildDefaultHttpHeaders("delivery-details");
    }

    @MetaData("行项数据")
    public HttpHeaders saleDeliveryDetails() {
        List<SaleDeliveryDetail> saleDeliveryDetails = bindingEntity.getSaleDeliveryDetails();
        if (BooleanUtils.toBoolean(getParameter("clone"))) {
            for (SaleDeliveryDetail saleDeliveryDetail : saleDeliveryDetails) {
                saleDeliveryDetail.resetCommonProperties();
            }
        }
        setModel(buildPageResultFromList(saleDeliveryDetails));
        return buildDefaultHttpHeaders();
    }

    public HttpHeaders pickSave() {
        saleDeliveryService.pickSave(bindingEntity);
        setModel(OperationResult.buildSuccessResult("拣货完成"));
        return buildDefaultHttpHeaders();
    }

    public HttpHeaders deliverySave() {
        Validation.isTrue(!StorageModeEnum.SA.equals(bindingEntity.getStorageMode()), "代发销售单只能通过‘采购录入物流信息’来发货");
        saleDeliveryService.deliverySave(bindingEntity);
        setModel(OperationResult.buildSuccessResult("发货完成"));
        return buildDefaultHttpHeaders();
    }

    public HttpHeaders chargeAgainst() {
        if (bindingEntity.getDeliveryTime() != null && bindingEntity.getBoxOrderDetail() != null) {
            User loginUser = this.getLogonUser();
            List<Role> roles = roleService.findR2RolesForUser(loginUser);
            Boolean flag = false;
            for (Role role : roles) {
                if ("ROLE_MYT_ADMIN".equals(role.getCode()) || "ROLE_ADMIN".equals(role.getCode())) {
                    flag = true;
                }
            }
            Validation.isTrue(flag, "已发货并关联销售订单，请交给系统管理人员红冲");

        }
        saleDeliveryService.chargeAgainst(bindingEntity);
        setModel(OperationResult.buildSuccessResult("红冲完成"));
        return buildDefaultHttpHeaders();
    }

    public Map<Long, String> getExpressDataTemplatesMap() {
        Map<Long, String> dataMap = new LinkedHashMap<Long, String>();
        GroupPropertyFilter groupPropertyFilter = GroupPropertyFilter.buildDefaultAndGroupFilter();
        List<ExpressDataTemplate> expressDataTemplates = expressDataTemplateService.findByFilters(groupPropertyFilter);
        for (ExpressDataTemplate item : expressDataTemplates) {
            dataMap.put(item.getId(), item.getDisplay());
        }
        return dataMap;
    }

    public Map<String, String> getReferenceSourceMap() {
        return this.findMapDataByDataDictPrimaryKey("MYT_SALE_DELIVERY_ORDER_SOURCE");
    }

    @MetaData(value = "付款会计科目数据")
    public Map<Long, String> getPaymentAccountSubjects() {
        Map<Long, String> datas = Maps.newLinkedHashMap();
        Iterable<AccountSubject> items = accountSubjectService.findPaymentAccountSubjects();
        for (AccountSubject item : items) {
            datas.put(item.getId(), item.getDisplay());
        }
        return datas;
    }

    @MetaData(value = "销售员业绩统计")
    @SecurityControlIgnore
    public HttpHeaders findByGroupSaler() {
        setModel(findByGroupAggregate("voucherUser.id", "voucherUser.signinid", "voucherUser.nick", "max(profitRate)", "min(profitRate)", "sum(profitAmount)", "sum(totalAmount)",
                "sum(commodityCostAmount)", "case(equal(sum(totalAmount),0),-1,quot(sum(profitAmount),sum(totalAmount)))"));
        return buildDefaultHttpHeaders();
    }

    @MetaData("库存变更记录")
    public HttpHeaders stockInOuts() {
        List<StockInOut> stockInOuts = stockInOutService.findByVoucherAndVoucherType(bindingEntity.getVoucher(), VoucherTypeEnum.XS);
        setModel(buildPageResultFromList(stockInOuts));
        return buildDefaultHttpHeaders();
    }

    @MetaData("财会记录")
    public HttpHeaders accountInOuts() {
        List<AccountInOut> accountInOuts = accountInOutService.findByVoucherAndVoucherType(bindingEntity.getVoucher(), VoucherTypeEnum.XS);
        setModel(buildPageResultFromList(accountInOuts));
        return buildDefaultHttpHeaders();
    }

    @Override
    public HttpHeaders revisionList() {
        return super.revisionList();
    }

    @Override
    public HttpHeaders revisionCompare() {
        return super.revisionCompare();
    }

    public HttpHeaders sendDeliveryNotifyEmail() {
        businessNotifyService.sendDeliveryNotifyEmail(bindingEntity);
        setModel(OperationResult.buildSuccessResult("邮件发送成功"));
        return buildDefaultHttpHeaders();
    }

    public HttpHeaders preDeliveryNotify() {
        Validation.isTrue(bindingEntity.getDeliveryTime() != null, "请先完成发货，再发送通知邮件和短信");
        SaleDelivery saleDelivery = saleDeliveryService.findOne(bindingEntity.getId());
        Map<String, Object> dataMap = new HashMap<String, Object>();
        dataMap.put("saleDelivery", saleDelivery);
        dataMap.put("saleDeliveryDetails", saleDelivery.getSaleDeliveryDetails());
        dataMap.put("customerProfile", saleDelivery.getCustomerProfile());
        dataMap.put("todayDate", new Date());
        String preEmailContent = freemarkerService.processTemplateByFileName("DELIVERY_NOTIFY_EMAIL", dataMap);
        String preEmail = saleDelivery.getCustomerProfile().getEmail();
        String preSub = "发货通知";
        this.getRequest().setAttribute("preEmailContent", preEmailContent);
        this.getRequest().setAttribute("preEmail", preEmail);
        this.getRequest().setAttribute("preSub", preSub);

        Map<String, Object> dataMap2 = new HashMap<String, Object>();
        // dataMap2.put("title", bindingEntity.getTitle());
        // if (bindingEntity.getBoxOrderDetail() != null) {
        // dataMap2.put("orderSeq",
        // bindingEntity.getBoxOrderDetail().getBoxOrder().getOrderSeq());
        // }
        // dataMap2.put("title", bindingEntity.getTitle());
        dataMap2.put("saleDelivery", saleDelivery);
        dataMap2.put("customerProfile", saleDelivery.getCustomerProfile());
        dataMap2.put("logistics", saleDelivery.getLogistics());
        String preSmsContent = freemarkerService.processTemplateByFileName("DELIVERY_NOTIFY_SMS", dataMap2);
        String preMobile = saleDelivery.getMobilePhone() == null ? saleDelivery.getCustomerProfile().getMobilePhone() : saleDelivery.getMobilePhone();
        this.getRequest().setAttribute("preSmsContent", preSmsContent);
        this.getRequest().setAttribute("preMobile", preMobile);
        return buildDefaultHttpHeaders("notify");
    }

    public HttpHeaders deliveryNotify() {

        Validation.isTrue(bindingEntity.getDeliveryTime() != null, "请先完成发货，再发送通知邮件和短信");
        String preSmsContent = null;
        String preMobile = null;
        if (BooleanUtils.toBoolean(getParameter("booleanSendSms"))) {
            preSmsContent = getParameter("preSmsContent");
            preMobile = getParameter("preMobile");
        }

        String preEmailContent = null;
        String preEmail = null;
        String preSub = null;
        if (BooleanUtils.toBoolean(getParameter("booleanSendEmail"))) {
            preEmailContent = getParameter("preEmailContent");
            preEmail = getParameter("preEmail");
            preSub = getParameter("preSub");
        }
        saleDeliveryService.deliveryNotify(preEmailContent, preEmail, preSub, preSmsContent, preMobile);
        setModel(OperationResult.buildSuccessResult("发送成功"));
        return buildDefaultHttpHeaders();
    }

    public String getGeocode() {
        return geocode;
    }

    public void setGeocode(String geocode) {
        this.geocode = geocode;
    }

}